#ifndef __GAME_GUID_H__
#define __GAME_GUID_H__

#include <string>
#include <cstdint>

#define USE_NLOHMANN_JSON 1

#if USE_NLOHMANN_JSON
#include "nlohmann/json.hpp"
#endif

namespace PocketSurvival::Engine
{
    class GameGuid
    {
    public:
        union GuidData
        {
            char buff[16];
            struct
            {
                int64_t ab;
                int64_t cd;
            };
            struct
            {
                int32_t a;
                int32_t b;
                int32_t c;
                int32_t d;
            };
        } guidData;
    
    public:
        GameGuid();
        explicit GameGuid(int64_t ab, int64_t cd) noexcept;
        explicit GameGuid(const std::string& guidStr);

        ~GameGuid();
        inline char* data()
        {
            return guidData.buff;
        }

        inline const char * constData() const
        {
            return guidData.buff;
        }
        std::string toString() const;
        void createRandom();
        static const GameGuid& GetZeroGuid();
        
        void fromString(const std::string& guidStr);

        inline int64_t toKey() const;

        friend constexpr inline bool operator==(const GameGuid &left, const GameGuid &right)
        {
            return (left.guidData.ab == right.guidData.ab) && (left.guidData.cd == right.guidData.cd);
        }
        friend constexpr inline bool operator!=(const GameGuid &left, const GameGuid &right)
        {
            return (left.guidData.ab != right.guidData.ab) || (left.guidData.cd != right.guidData.cd);
        }
        inline bool operator<(const GameGuid& other) const
        {
            if(guidData.ab < other.guidData.ab)
            {
                return true;
            }
            else if(guidData.ab == other.guidData.ab && guidData.cd < other.guidData.cd)
            {
                return true;
            }
            return false;
        }


#if USE_NLOHMANN_JSON
        friend inline void to_json(nlohmann::json &json, const GameGuid &guid);
        friend inline void from_json(const nlohmann::json &json, GameGuid &guid);
#endif

        inline size_t operator()(const GameGuid& guid) const
        {
            return guid.toKey();
        }
        inline bool operator()(const GameGuid& left, const GameGuid &right) const noexcept
        {
            return (left == right);
        }

    };

    inline GameGuid::GameGuid(int64_t ab, int64_t cd) noexcept
    {
        guidData.ab = ab;
        guidData.cd = cd;
    }

    inline int64_t GameGuid::toKey() const
    {
        return guidData.ab ^ guidData.cd;
    }

#if USE_NLOHMANN_JSON

    inline void to_json(nlohmann::json &json, const GameGuid &guid)
    {
        json = guid.toString();
    }
    inline void from_json(const nlohmann::json &json, GameGuid &guid)
    {
        guid.fromString(json.get<std::string>());
    }

#endif


}

#undef USE_NLOHMANN_JSON

#endif